#pragma once
#include <iostream>
#include "Iterator.hpp"
#include <assert.h>
namespace wzh
{
	template<class T>
	class MyVector
	{
		typedef T* iterator;
	public:
		MyVector()
			:_start(nullptr)
			,_finish(nullptr)
			,_end_of_storage(nullptr)
		{}

		MyVector(size_t size, const T& val = T())
		{
			iterator tmp = new T[size + 1];
			for (int i = 0; i < size; i++)
			{
				tmp[i] = val;
			}
			_start = tmp;
			_finish = _end_of_storage = tmp + size;
		}

		MyVector(const MyVector& myv)
		{
			size_t size = myv.Size();
			size_t capacity = myv.Capacity();
			MyVector tmp(capacity);
			for (int i = 0; i < size; i++)
			{
				tmp[i] = myv[i];
			}
			Swap(tmp);
		}

		~MyVector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}

		T& operator[](size_t index) const
		{
			return _start[index];
		}

		MyVector& operator=(const MyVector& myv)
		{
			MyVector tmp(myv);
			Swap(tmp);
			return *this;
		}

		void Swap(MyVector& myv)
		{
			std::swap(_start, myv._start);
			std::swap(_finish, myv._finish);
			std::swap(_end_of_storage, myv._end_of_storage);
		}

		size_t Size() const
		{
			return _finish - _start;
		}

		size_t Capacity() const
		{
			return _end_of_storage - _start;
		}

		void ReSize(size_t size, T& val = T())
		{
			int cur_sz = Size();
			int cur_cap = Capacity();
			if (size > cur_sz)
			{
				if (size > cur_cap)
				{
					MyVector tmp(size);
					for (int i = 0; i < cur_sz; i++)
					{
						tmp[i] = _start[i];
					}
					for (int i = cur_sz; i < size; i++)
					{
						tmp[i] = val;
					}
					Swap(tmp);
				}
				else
				{
					for (int i = cur_sz; i < cur_cap; i++)
					{
						_start[i] = val;
					}
				}
			}
			_finish = _start + size;
		}

		void ReServer(size_t size)
		{
			if (size > Capacity())
			{
				MyVector tmp(size);
				for (int i = 0; i < Size(); i++)
				{
					tmp[i] = _start[i];
				}
				tmp._finish = tmp._start + Size();
				Swap(tmp);
			}
		}

		bool Empty()
		{
			return _start == _finish ? true : false;
		}

		T& Front()
		{
			return *_start;
		}

		T& Back()
		{
			return *(_finish - 1);
		}

		void InSert(iterator pos, size_t n, const T& val)
		{
			assert(pos >= _start && pos <= _finish);
			if (_finish + n > _end_of_storage)
			{
				ReServer(2 * Capacity() + n);
				pos = begin();
			}
			std::copy_backward(pos, _finish, _finish + n);
			iterator it = pos;
			for (int i = 0; i < n; i++)
			{
				*it = val;
				++it;
			}
			_finish += n;
		}

		void push_back(const T& val)
		{
			InSert(end(), 1, val);
		}

		void Erase(iterator begin, iterator end)
		{
			assert(begin < end && begin >= _start && begin < _finish);
			if (end >= _finish)
			{
				_finish = begin;
			}
			else
			{
				std::copy(end, _finish, begin);
				_finish = begin + (_finish - end + 1);
			}
		}

		void Pop_Back()
		{
			Erase(end() - 1, end());
		}

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};
}